; String slicing library
; HL = Str pointer
; DE = String start
; BC = String character end
; A register => 0 => the HL pointer wont' be freed from the HEAP
; e.g. a$(5 TO 10) => HL = a$; DE = 5; BC = 10
; This implements a$(X to Y) being X and Y first and
; last characters respectively. If X > Y, NULL is returned
; Otherwise returns a pointer to a$ FROM X to Y (starting from 0)
; if Y > len(a$), then a$ will be padded with spaces (reallocating
; it in dynamic memory if needed). Returns pointer (HL) to resulting
; string. NULL (0) if no memory for padding.
;
#include once <strlen.asm>
#include once <alloc.asm>
#include once <free.asm>
__STRSLICE:			; Callee entry
pla                  ;- pop hl			; Return ADDRESS
sta z80_h
pla
sta z80_l
pla                  ;- pop bc			; Last char pos
sta z80_b
pla
sta z80_c
pla                  ;- pop de			; 1st char pos
sta z80_d
pla
sta z80_e
tsx                  ;- ex (sp), hl		; CALLEE. -> String start
lda $0103,x
ldy z80_h
sta z80_h
tya
sta $0103,x
lda $0104,x
ldy z80_l
sta z80_l
tya
sta $104,x

__STRSLICE_FAST:	; __FASTCALL__ Entry
                     ;- PROC
                     ;- LOCAL __CONT
                     ;- LOCAL __EMPTY
                     ;- LOCAL __FREE_ON_EXIT
lda z80_l            ;- push hl			; Stores original HL pointer to be recovered on exit
pha
lda z80_h
pha
ldx z80_ap           ;- ex af,af'		; Saves A register for later
sta z80_ap
txa
lda z80_l            ;- push hl
pha
lda z80_h
pha
jsr __STRLEN         ;- call __STRLEN
inc z80_c            ;- inc bc			; Last character position + 1 (string starts from 0)
bne *+4
inc z80_b
ora z80_a            ;- or a
                     ;- sbc hl, bc		; Compares length with last char position
jcs __CONT           ;- jr nc, __CONT	; If Carry => We must copy to end of string
lda z80_l            ;- add hl,bc		; Restore back original LEN(a$) in HL
clc
adc z80_c
sta z80_l
lda z80_h
adc z80_b
sta z80_h
lda z80_h            ;- ld b,h
sta z80_b
lda z80_l            ;- ld c,l			; Copy to the end of str
sta z80_c
                     ;- ccf				; Clears Carry flag for next subtraction

__CONT:
lda z80_b            ;- ld h,b
sta z80_h
lda z80_c            ;- ld l,c			; HL = Last char position to copy (1 for char 0, 2 for char 1, etc)
sta z80_l
                     ;- sbc hl, de		; HL = LEN(a$) - DE => Number of chars to copy
jeq __EMPTY          ;- jr z, __EMPTY	; 0 Chars to copy => Return HL = 0 (NULL STR)
jcc __EMPTY          ;- jr c, __EMPTY	; If Carry => Nothing to return (NULL STR)
lda z80_h            ;- ld b,h
sta z80_b
lda z80_l            ;- ld c,l			; BC = Number of chars to copy
sta z80_c
inc z80_c            ;- inc bc
bne *+4
inc z80_b
inc z80_c            ;- inc bc			; +2 bytes for string length number
bne *+4
inc z80_b
lda z80_c            ;- push bc
pha
lda z80_b
pha
lda z80_e            ;- push de
pha
lda z80_d
pha
jsr __MEM_ALLOC      ;- call __MEM_ALLOC
pla                  ;- pop de
sta z80_d
pla
sta z80_e
pla                  ;- pop bc
sta z80_b
pla
sta z80_c
lda z80_h            ;- ld a,h
sta z80_a
ora z80_l            ;- or l
jeq __EMPTY          ;- jr z, __EMPTY	; Return if NULL (no memory)
                     ;- dec bc
                     ;- dec bc			; Number of chars to copy (Len of slice)
lda z80_c            ;- ld (hl),c
ldy #$00
sta (z80_hl),y
inc z80_l            ;- inc hl
bne *+4
inc z80_h
lda z80_b            ;- ld (hl),b
ldy #$00
sta (z80_hl),y
inc z80_l            ;- inc hl			; Stores new string length
bne *+4
inc z80_h
tsx                  ;- ex (sp), hl		; Pointer to A$ now in HL; Pointer to new string chars in Stack
lda $0103,x
ldy z80_h
sta z80_h
tya
sta $0103,x
lda $0104,x
ldy z80_l
sta z80_l
tya
sta $104,x
inc z80_l            ;- inc hl
bne *+4
inc z80_h
inc z80_l            ;- inc hl			; Skip string length
bne *+4
inc z80_h
clc                  ;- add hl,de		; Were to start from A$
lda z80_l
adc z80_e
sta z80_l
lda z80_h
adc z80_d
sta z80_h
pla                  ;- pop de			; Start of new string chars
sta z80_d
pla
sta z80_e
lda z80_e            ;- push de			; Stores it again
pha
lda z80_d
pha
                     ;- ldir			; Copies BC chars
pla                  ;- pop de
sta z80_d
pla
sta z80_e
                     ;- dec de
                     ;- dec de			; Points to String LEN start
lda z80_e            ;- ex de,hl		; Returns it in HL
ldx z80_l
stx z80_e
sta z80_l
lda z80_d
ldx z80_h
stx z80_d
sta z80_h
jmp __FREE_ON_EXIT   ;- jr __FREE_ON_EXIT

__EMPTY:
; Return NULL (empty) string
pla                  ;- pop hl
sta z80_h
pla
sta z80_l
lda #<0              ;- ld hl, 0		; Return NULL
sta z80_l
lda #>0
sta z80_h

__FREE_ON_EXIT:
ldx z80_ap           ;- ex af,af'		; Recover original A register
sta z80_ap
txa
tsx                  ;- ex (sp),hl		; Original HL pointer
lda $0103,x
ldy z80_h
sta z80_h
tya
sta $0103,x
lda $0104,x
ldy z80_l
sta z80_l
tya
sta $104,x
ora z80_a            ;- or a
beq *+5              ;- call nz, __MEM_FREE
jsr __MEM_FREE
pla                  ;- pop hl			; Recover result
sta z80_h
pla
sta z80_l
rts                  ;- ret
                     ;- ENDP

